package com.github.bridge.client.esign.request;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;

@Data
public class CreateAndStartRequest {

    @NotBlank
    @Schema(description = "流程主题", requiredMode = Schema.RequiredMode.REQUIRED)
    private String subject;

    @Schema(description = "第三方签署流程业务id 建议传入")
    private String businessNo;

    @NotBlank
    @Schema(description = "业务类型ID从统一门户-业务模板-配置-签署方式获取“签署业务类型编码）", requiredMode = Schema.RequiredMode.REQUIRED)
    private String businessTypeCode;

    @Schema(description = "是否强制阅读至最后一页：0否，1是；默认为0")
    private Integer readComplete;

    @Schema(description = "是否开启签约须知：0否，1是；默认为0")
    private Integer advertisement;

    @Schema(description = "签约须知信息")
    private ExtenderParam extenderParams;

    @Length(max = 200)
    @Schema(description = "流程备注（长度200）")
    private String remark;

    @Schema(description = "签署截止日期：超过签署截止日期后流程将自动失效，不传默认为长期有效")
    private String signFlowExpireTime;

    @Schema(description = "手动发起/结束配置项")
    private ManualConfig manualConfig;

    @NotNull
    @Schema(description = "发起方信息集合（仅支持内部用户）", requiredMode = Schema.RequiredMode.REQUIRED)
    private InitiatorInfo initiatorInfo;

    @JsonProperty(value = "CCInfos")
    @Schema(description = "抄送方信息集合")
    private CCInfo CCInfos;

    @Schema(description = "签署完成重定向地址")
    private String redirectUrl;

    @Schema(description = "自动重定向时间 时间：支持0-60之间整数；单位为秒 不传值/传空，默认为3 如果传0，签署页所有文件签署成功，提交签署后则会自动跳转到redirectUrl传入的地址")
    private Integer autoRedirectTime;

    @Schema(description = "意愿认证完成、签署完成的APP跳转地址，支持传入不同的设备标识，实现跳转至对应设备下的APP地址。" +
            "1、在app的webview.UA里注入appName（如ios、ios9、android、android12）" +
            "2、签署页通过解析UA，匹配流程的appName信息：" +
            "2.1、当appName识别到ios，跳转至ios对应的appSchema。" +
            "2.2、当appName识别到ios9，跳转至ios9对应的appSchema。" +
            "2.3、当appName识别到android，跳转至android对应的appSchema。" +
            "2.4、当appName识别到android12，跳转至android12对应的appSchema。" +
            "3、建议开发者在配置appSchema时，校验签署流程状态后再自行重定向至对应页面。")
    private List<AppRedirectInfo> appRedirectInfo;

    @Schema(description = "签署成功回调")
    private String signNotifyUrl;

    @Schema(description = "付费方：1：发起方、2：相对方，默认1；需要开启“相对方付费”功能后，该参数生效。")
    private Integer chargingType;

    @Schema(description = "流程文档信息集合")
    private List<SignFile> signFiles;

    @Schema(description = "附件信息集合")
    private List<Attachment> attachments;


    @Schema(description = "签署方信息集合")
    private List<SignerInfo> signerInfos;

    @Data
    public static class ExtenderParam {

        @Schema(description = "签署须知标题，长度1-10，允许输入中文、字母、字符、空格（首尾自动去空格）.不传则使用业务模板的签署须知标题")
        private String noticeSignTitle;

        @Schema(description = "签署须知内容，长度1-200，允许输入中文、字母、字符、空格（首尾自动去空格）.不传则使用业务模板的签署须知内容")
        private String noticeSignContent;
    }

    @Data
    public static class ManualConfig {
        @Schema(description = "流程发起方式：默认自动开启。0自动开启：创建后流程状态=签署中 1手动开启：创建后流程状态=草稿，在出参返回签署区设置页地址")
        private Integer startMode;
        @Schema(description = "流程结束方式：默认自动结束。0自动结束：所有签署方签署完成，流程自动完成 1手动结束：所有签署方签署完成，需调用无节点签署的【结束签署流程】接口，主动结束流程")
        private Integer finishMode;
        @Schema(description = "签署区设置页配置项（startMode传1手动开启时此参数生效，不传使用默认值。仅草稿状态的流程可以在签署区设置页设置）签署区设置页按钮：【保存】（固定显示），【发起】（根据showStartButton参数配置）")
        private SigningAreaPageConfig signingAreaPageConfig;
    }

    @Data
    public static class SigningAreaPageConfig {
        @Schema(description = "允许查看、操作的用户类型：INITIATOR发起人，ALL-INNERS所有内部用户，默认INITIATOR")
        private String allowUsersType;
        @Schema(description = "发起人打开签署区设置页，是否展示【发起】按钮，0：不显示按钮，1：显示按钮。默认1")
        private Integer showStartButton;
        @Schema(description = "签署区设置页重定向地址。页面保存、直接发起成功，触发跳转至重定向地址")
        private String areaPageRedirectUrl;
    }

    @Data
    public static class InitiatorInfo {
        @Schema(description = "用户编码（本系统的唯一标识）。userCode、customAccountNo二选一必填，如果userCode、customAccountNo两者都有值，以userCode为准")
        private String userCode;

        @Schema(description = "用户账号（客户系统的唯一标识）。userCode、customAccountNo二选一必填，如果userCode、customAccountNo两者都有值，以userCode为准")
        private String customAccountNo;

        @Schema(description = "用户默认组织编号/其他组织编号，需与organizationCode匹配。" +
                "//不校验与企业的隶属关系，需校验与用户的隶属关系。")
        private String departmentCode;

        @Schema(description = "用户默认组织账号（客户系统的唯一标识），需与organizationCode、customOrgNo匹配。如果departmentCode  、customDepartmentNo 两者都有值，以departmentCode 为准")
        private String customDepartmentNo;

        @Schema(description = "用户所属企业编码（本系统的唯一标识）。如果organizationCode、customOrgNo两者都有值，以organizationCode为准")
        private String organizationCode;

        @Schema(description = "用户所属企业账号（客户系统的唯一标识）。如果organizationCode、customOrgNo两者都有值，以organizationCode为准")
        private String customOrgNo;
    }

    @Data
    private static class CCInfo {
        @Schema(description = "用户类型：1-内部，2-相对方")
        private String userType;

        @Schema(description = "用户编码（本系统的唯一标识）。userCode、customAccountNo二选一必填，如果userCode、customAccountNo两者都有值，以userCode为准")
        private String userCode;

        @Schema(description = "用户账号（客户系统的唯一标识）。userCode、customAccountNo二选一必填，如果userCode、customAccountNo两者都有值，以userCode为准")
        private String customAccountNo;

        @Schema(description = "用户默认组织编号/其他组织编号（本系统的唯一标识），需与organizationCode、customOrgNo匹配。如果departmentCode  、customDepartmentNo 两者都有值，以departmentCode 为准")
        private String departmentCode;

        @Schema(description = "用户默认组织账号（客户系统的唯一标识），需与organizationCode、customOrgNo匹配。如果departmentCode  、customDepartmentNo 两者都有值，以departmentCode 为准")
        private String customDepartmentNo;

        @Schema(description = "用户所属企业编码（本系统的唯一标识）。如果organizationCode、customOrgNo两者都有值，以organizationCode为准 个人相对方customOrgNo传 GRXDF（即：个人相对方首字母大写）")
        private String organizationCode;

        @Schema(description = "用户所属企业账号（客户系统的唯一标识）。如果organizationCode、customOrgNo两者都有值，以organizationCode为准 个人相对方customOrgNo传 GRXDF（即：个人相对方首字母大写）")
        private String customOrgNo;

    }

    @Data
    public static class AppRedirectInfo {

        @Schema(description = "APP设备标识", requiredMode = Schema.RequiredMode.REQUIRED)
        private String appName;

        @Schema(description = "APP跳转协议", requiredMode = Schema.RequiredMode.REQUIRED)
        private String appSchema;
    }

    @Data
    public static class SignFile {
        @Schema(description = "签署文档fileKey（支持PDF与OFD格式文件）", requiredMode = Schema.RequiredMode.REQUIRED)
        private String fileKey;

        @Schema(description = "文档顺序,用于页面文档顺序显示")
        private Integer fileOrder;

        @Schema(description = "是否添加二维码，0否，1是；默认为0（值为1时二维码配置以接口传值为准）")
        private Integer qrFile;

        @Schema(description = "二维码配置集合")
        private QrFileInfo qrFileInfos;
    }

    @Data
    public static class QrFileInfo {

        @Schema(description = "二维码有效时间，可传入1-36500区间任意整数，单位为天，默认为30天")
        private Integer qrEffectiveTime;

        @Schema(description = "二维码宽度：只支持正方形二维码，宽度、长度共用一个参数，默认96 ；支持96～149（PX）之间整数")
        private Integer qrWidth;

        @Schema(description = "二维码查看权限：0-内部所有用户， 1-内部流程参与人 ，2-公开，默认为1")
        private Integer qrView;

        @Schema(description = "水印页数：1-首页 2-末页 3-所有页 默认为3")
        private Integer watermarkPage;

        @Schema(description = "水印位置：1-左上角  2-右上角 3-左下角 4-右下角 默认为1")
        private Integer watermarkPosition;

        @Schema(description = "x偏移量：支持0-99999之间整数；默认为0")
        private Integer qrPosX;

        @Schema(description = "y偏移量：支持0-99999之间整数；默认为0")
        private Integer qrPosY;
    }

    @Data
    public static class Attachment {
        @Schema(description = "附件fileKey", requiredMode = Schema.RequiredMode.REQUIRED)
        private String fileKey;

        @Schema(description = "附件顺序,用于页面文档顺序显示")
        private Integer fileOrder;

    }

    @Data
    public static class SignerInfo {
        @Schema(description = "用户类型：1-企业用户，2-个人用户")
        private String userType;

        @Schema(description = "用户编码（本系统的唯一标识）。不为空时，签署主体视为个人。")
        private String userCode;

        @Schema(description = "用户账号（客户系统的唯一标识）。如果userCode、customAccountNo两者都有值，以userCode为准")
        private String customAccountNo;

        @Schema(description = "用户默认组织编号/其他组织编号，需与organizationCode匹配。//不校验与企业的隶属关系，需校验与用户的隶属关系。")
        private String departmentCode;

        @Schema(description = "用户默认组织账号/其他组织账号（客户系统的唯一标识），需与userCode、customAccountNo匹配。" +
                "如果departmentCode  、customDepartmentNo 两者都有值，以departmentCode 为准。" +
                "//不校验与企业的隶属关系，需校验与用户的隶属关系。")
        private String customDepartmentNo;

        @Schema(description = "企业编码（本系统的唯一标识）。不为空时，签署主体视为企业。" +
                "如果organizationCode、customOrgNo两者都有值，以organizationCode为准。" +
                "//不校验与用户、部门的隶属关系。")
        private String organizationCode;

        @Schema(description = "企业账号（客户系统的唯一标识）。不为空时，签署主体视为企业。" +
                "如果organizationCode、customOrgNo两者都有值，以organizationCode为准。" +
                "//不校验与用户、部门的隶属关系。")
        private String customOrgNo;

        @Schema(description = "签署人所在签署网络节点id；需要使用签署网络像其他系统发送签署时必传")
        private String estpNode;

        @Schema(description = "是否允许添加附件：0-否，1-是；默认为0")
        private Integer allowAddAttachment;

        @Schema(description = "是否自动签署：0-否，1-是；默认为0")
        private Boolean autoSign;

        @Schema(description = "一键落章默认状态，0-关闭，1-开启，不传或传空时默认为1-开启")
        private Boolean batchSignDefault;

        @Schema(description = "可用印章介质：0-云印章及UKey印章、1-仅UKey印章、2-仅云印章。不传或传空时默认为2 外部用户不支持UKey印章\n" +
                "UKey印章不支持静默签署")
        private Boolean UkeyOnly;

        @Schema(description = "签署节点，最小为1。节点之间有顺序，节点内的签署方都签署完成后，再进入下一个节点进行签署")
        private Integer signNode;

        @Schema(description = "节点内排序方式：0-顺序签，1-无序签，2-或签，默认0")
        private String signMode;

        @Schema(description = "节点内顺序，允许的顺序值为1-99999，无值时默认1。")
        private Integer signOrder;

        @Schema(description = "定印章类型，签署主体为个人是不支持指定印章类型，默认不指定，支持多个，用“,”隔开\n" +
                "1.内部企业盖章数据来源于企业授权给经办人的印章类型（包含法人章）\n" +
                "2.外部企业盖章数据来源于固定印章类型：" +
                "PUBLIC ：公章" +
                "CONTRACT：合同专用章" +
                "FINANCE：财务章" +
                "COMMON：其他" +
                "PERSONNEL：人事专用章" +
                "LEGAL-PERSON-SEAL：法人章" +
                "3.如果sealTypeCode、sealId两者都有值，校验二者关系")
        private String sealTypeCode;

        @Schema(description = "签署任务信息" +
                "1、指定文档进行签署；" +
                "2、未指定的文档：" +
                "2.1未指定当前签署方、指定了其他签署方签署，则对当前签署方只读。" +
                "2.2未指定任何签署方，则对所有签署方必签（自由签）。")
        private List<SealInfo> sealInfos;

    }

    @Data
    public static class SealInfo {

        @NotBlank(message = "签署文档fileKey不能为空")
        @Schema(description = "签署文档fileKey", requiredMode = Schema.RequiredMode.REQUIRED)
        private String fileKey;

        @Schema(description = "签署位置信息;必须指定签署位置信息才可以签署")
        private List<SignConfig> signConfigs;

    }

    @Data
    public static class SignConfig {
        @Schema(description = "是否自由签章，0否，1是；默认为0 自由签章不限制签章个数")
        private Boolean freeMode;

        @Schema(description = "签章类型 指定签署印章类型：PERSON-SEAL-个人印章、COMMON-SEAL-企业授权印章、LEGAL-PERSON-SEAL-法人章")
        private String signatureType;

        @Schema(description = "是否强制手绘签名：0否，1是；默认为0" +
                "当signatureType=PERSON-SEAL时，生效")
        private Boolean handEnable;

        @Schema(description = "印章id，需要校验用印权限；如果sealTypeCode、signatureType有值，需同时校验印章类型是否一致。" +
                "自由签签署区可指定多个，多个逗号间隔" +
                "PDF文件可使用国际标准印章、中国标准印章进行签署；OFD文件使用中国标准印章进行签署")
        private String sealId;

        @Schema(description = "是否允许移动，0否，1是；" +
                "1是：签署时可以在当前页面移动签署区位置；" +
                "0否：签署时不可以移动签署区位置；" +
                "不传值/传空，表示读取业务模板中【签署区/备注区默认可移动】参数，")
        private Boolean allowMove;

        @Schema(description = "签名域宽度，为空则取印章大小。单位：px")
        private Integer width;

        @Schema(description = "签署类型: COMMON-SIGN : 普通（包含单页签、多页签)， EDGE-SIGN:骑缝，KEYWORD-SIGN:关键字，默认COMMON-SIGN\n" +
                "说明：自由签签署区（freeMode=1），签署类型支持同时传COMMON-SIGN,EDGE-SIGN，英文逗号,分隔")
        private String signType;

        @Schema(description = "骑缝章签署范围：0-指定页（默认全选），1-奇数页，2-偶数页，默认0")
        private Integer edgeScope;

        @Schema(description = "关键字定位信息集合")
        private KeywordInfo keywordInfo;

        @Schema(description = "签署页码;连续页码用'-'连接，单独页码用','连接")
        private Integer pageNo;

        @Schema(description = "x轴偏移量;骑缝签无视该参数" +
                "PDF文件以页面左下角为原点，x偏移量正数向右偏移，负数向左偏移" +
                "OFD文件以页面左上角为原点，x偏移量正数向右偏移，负数向左偏移")
        private Float posX;

        @Schema(description = "y轴偏移量" +
                "PDF文件以页面左下角为原点，y偏移量正数向上偏移，负数向下偏移" +
                "OFD文件以页面左上角为原点，y偏移量正数向下偏移，负数向上偏移" +
                "盖章效果：印章将以签署区定位点作为中心点进行签署")
        private Float posY;

        @Schema(description = "否添加签署时间" +
                "指定签场景：0-否 1-是，" +
                "addSignDate不传，落章默认不展示签署日期，日期配置不禁用；addSignDate=1时需传入sealSignDatePositionInfo" +
                "自由签场景：0-否 1-是，addSignDate不传，落章默认不展示签署日期，日期配置不禁用；addSignDate=0无需传入sealSignDatePositionInfo\n" +
                "OFD文件不支持添加签署时间")
        private Boolean addSignDate;

        @Schema(description = "签章日期信息")
        private SealSignDatePositionInfo sealSignDatePositionInfo;

        @Schema(description = "签署区类型，默认值为 0。" +
                "0 - 签章区（用于加盖印章或签名），1 - 备注区（用于添加备注文字信息）")
        private Integer signFieldType;

        @Schema(description = "备注签署区配置合集" +
                "（备注签支持个人签署方、企业经办人)")
        private RemarkSignConfig remarkSignConfig;

    }

    @Data
    public static class KeywordInfo {
        @Schema(description = "关键字（以关键字形成的矩形区域的左下角为参考点进行定位）")
        private String keyword;

        @Schema(description = "指定签署某个位置关键字,受页码范围控制。-1为最后一个,超过关键字总数选中最后一个")
        private Integer keywordIndex;

        @Schema(description = "关键字横坐标偏移量 PDF/OFD文件以关键字形成的矩形区域的左下角为原点，x偏移量正数向右偏移，负数向左偏移")
        private Float offsetPosX;

        @Schema(description = "关键字纵坐标偏移量 PDF/OFD文件以关键字形成的矩形区域的左下角为原点，y偏移量正数向上偏移，负数向下偏移")
        private Float offsetPosY;

    }

    @Data
    public static class SealSignDatePositionInfo {
        @Schema(description = "签章日期时间格式，1：yyyy-MM-dd、2：yyyy年mm月dd日、3：yyyy/MM/dd，默认1")
        private Integer sealSign;
        @Schema(description = "签署时间字体大小，最小为5，最大为72，默认16")
        private Integer fontSize;
        @Schema(description = "x坐标，参数posX、posY无值且addSignDate开启表示在签署区下方添加签署时间 PDF文件以页面左下角为原点，y偏移量正数向上偏移，负数向下偏移 OFD文件以页面左上角为原点，y偏移量正数向下偏移，负数向上偏移")
        private Float posX;
        @Schema(description = "y坐标，参数posX、posY无值且addSignDate开启表示在签署区下方添加签署时间 PDF文件以页面左下角为原点，y偏移量正数向上偏移，负数向下偏移 OFD文件以页面左上角为原点，y偏移量正数向下偏移，负数向上偏移")
        private Float posY;

    }

    @Data
    public static class RemarkSignConfig {
        @Schema(description = "备注文字输入方式 1 - 手写抄录输入" +
                "2 - 键盘自由输入" +
                "3 - 表单输入")
        private Integer inputType;

        @Schema(description = "是否开启 AI 手写抄录校验 0 - 不开启" +
                "1 - 开启 AI 校验" +
                "2 - 强制 AI 校验" +
                "注：" +
                "inputType=1时此参数必须传值" +
                "inputType=2/3时此参数不生效")
        private Integer aiCheck;

        @Schema(description = "预设待抄录信息 最多支持50个汉字（含标点符号）" +
                "注：" +
                "inputType=1时此参数必须传值" +
                "inputType=2时此参数可选传值，传值后签署区上自动带入预抄录信息，支持用户修改。" +
                "inputType=3时此参数无需传值")
        private String remarkContent;

        @Schema(description = "采集任务ID inputType=1/2时此参数不生效" +
                "inputType=3时此参数必须传值")
        private String collectionTaskId;
        @Schema(description = "备注签署区提示信息 最多支持输入10个字符" +
                "不传则默认为“点击输入备注”")
        private String remarkPrompt;

        @Schema(description = "备注图片的宽度（单位为px） 取值区间：45--1240px")
        private Integer remarkFieldWidth;

        @Schema(description = "备注图片的高度（单位为px） 取值区间：45--1754px")
        private Integer remarkFieldHeight;

        @Schema(description = "备注文字大小，默认值14（px） 取值区间：6-72px" +
                "注：inputType=2/3时此参数必须传值 inputType=1时此参数不生效")
        private Integer remarkFontSize;

        @Schema(description = "允许设置多个 签署页码;连续页码用'-'连接，单独页码用','连接" +
                "若多页文件，未传页码仅传坐标，则默认第一页")
        private String remarkPageNo;

        @Schema(description = "备注区所在X坐标 PDF文件以页面左下角为原点，x偏移量正数向右偏移，负数向左偏移 " +
                "OFD文件以页面左上角为原点，x偏移量正数向右偏移，负数向左偏移" +
                "备注区显示效果：将以备注签署区定位点作为中心点显示备注区")
        private String remarkPosX;

        @Schema(description = "备注区所在Y坐标 PDF文件以页面左下角为原点，y偏移量正数向上偏移，负数向下偏移 " +
                "OFD文件以页面左上角为原点，y偏移量正数向下偏移，负数向上偏移")
        private String remarkPosY;

    }

}
